Room 持續性資料庫透過 SQLite 提供抽象層,可讓資料庫順暢存取,同時充分發揮 SQLite 的效用。特別是,Room 具有下列優點:
- SQL 查詢的編譯時間驗證。
- 盡可能減少重複且容易出錯的樣板程式碼的便利註解。
- 簡化資料庫遷移路徑。
基於以上考量,強烈建議您使用 Room 代替直接使用 SQLite API。
gradle.build(Module)
:
java
dependencies {
implementation "androidx.room:room-runtime:2.4.3"
annotationProcessor "androidx.room:room-compiler:2.4.3"
}
kotlin
dependencies {
implementation "androidx.room:room-runtime:2.4.3"
kapt "androidx.room:room-compiler:2.4.3"
}
@Entity
@Dao
@Database(entities = "步驟1的數據類")
註解 | 意思 |
---|---|
@PrimaryKey |
每個資料庫至少需設置一個主鍵字段(用以表示唯一值)。 @primaryKey(autoGenerate = true) 表示在建立物件的時候可以不用管這個欄位,Room會幫我們自動設定。 |
@ColumnInfo |
修飾字段作為資料庫中的行(column) |
DAO是用來定義操作資料的行為, 其中最常見的操作就是CRUD(增刪改查),我們只要使用對應的註解就行。
註解 | 意思 |
---|---|
C: @Insert |
新增資料 |
R: @Query |
查詢資料 |
U: @Update |
更新資料 |
D: @Delete |
刪除資料 |
注意!
所有DB操作請勿運行在UI thread,不然會噴exception。
@Entity
@Entity
public class User {
@PrimaryKey(autoGenerate = true)
private int uid;
@ColumnInfo(name = "first_name")
private String firstName;
@ColumnInfo(name = "last_name")
private String lastName;
@ColumnInfo(name = "age")
private int age;
public User(String firstName, String lastName, int age) {
this.firstName = firstName;
this.lastName = lastName;
this.age = age;
}
// ----- 該數據類所有屬性的getter和setter方法 -----
public int getAge() { return age; }
public void setName(int name) { this.age = name; }
public int getUid() { return uid; }
public void setUid(int uid) { this.uid = uid; }
public String getFirstName() { return firstName; }
public void setFirstName(String firstName) { this.firstName = firstName; }
public String getLastName() { return lastName; }
public void setLastName(String lastName) { this.lastName = lastName; }
}
@Dao
該接口用於定義操作資料的方法。
@Dao
public interface UserDao {
@Query("SELECT * FROM user")
List<User> getAll();
@Query("SELECT * FROM user WHERE uid IN (:userIds)")
List<User> loadAllByIds(int[] userIds);
@Query("SELECT * FROM user WHERE first_name LIKE :first AND last_name LIKE :last LIMIT 1")
User findByName(String first, String last);
@Insert
void insertAll(User ... users);
@Delete
void delete(User user);
}
@Database(entities = "步驟1的數據類")
@Database(entities = {User.class}, version = 1)
public abstract class AppDatabase extends RoomDatabase {
private final static String DB_NAME = "db_name"; // 資料庫名稱
private static volatile AppDatabase singleton;
// 必寫 Room才有辦法當我們把Dao和Entity關聯起來。
public abstract UserDao userDao();
// 使用單俐, 用以確保該應用只有一個實例, 這裡實現單例的方法是DCL(Double Check Lock)
// volatile和synchronized是用來保證線程安全和確保在不同線程也只有一個實例。
private AppDatabase() {} // 記得把構造方法設為私有
public static AppDatabase getInstance(Context context) {
if (singleton==null) {
synchronized (AppDatabase.class) {
if(singleton==null) {
singleton = Room.databaseBuilder(context, AppDatabase.class, DB_NAME).build();
}
}
}
return singleton;
}
}
完成前面步驟1~3, 就可以開始操作資料庫了
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
UserDao userDao = AppDatabase.getInstance(this).userDao(); // 取得User操作類
new Thread( () -> {
userDao.insertAll(new User("Gilbert", "Stemmler", 25)); // 添加用戶1
userDao.insertAll(new User("Juliette", "Macdonald", 30)); // 添加用戶2
}).start();
}
}
首先,需要先運行項目,然後開啟App Inspection
,等待一下即可看到步驟4
新增的數據。